package uuid

import (
	"crypto/md5"
	"fmt"
	"strconv"
	"time"
)

// 自增 id 生成器
func UidCreator(startIndex uint32) chan uint32 {
	c := make(chan uint32)
	var i uint32 = startIndex
	go func() {
		for {
			c <- i
			i++
		}
	} ()
	return c
}

var uidCreator = UidCreator(1)

// 获取自增 uint32 的 id
func GetAutoUid() uint32 {
	return <- uidCreator
}

// 自增 id 生成器
func TimeUidCreator() chan string {
	c := make(chan string)
	t := time.Now()
	i := 0
	go func() {
		for {
			ct := time.Now()
			if ct.Year() != t.Year() || ct.YearDay() != t.YearDay() || ct.Hour() != t.Hour() || ct.Minute() != t.Minute() {
				i = 1
				t = ct
			} else {
				i ++
			}
			c <- fmt.Sprintf("%d%02d%02d%02d%02d_%d", ct.Year(), ct.Month(), ct.Day(), ct.Hour(), ct.Minute(), i)
		}
	} ()
	return c
}

var timeUidCreator = TimeUidCreator()

// 获取时间相关的 uid
func GetTimeUid() string {
	return <- timeUidCreator
}

// 用户短 id 生成器，6位数及6位以上
type userShortId struct {
	usedIds 	map[int32]int32 	// 已经被使用的 id 列表
	liveIds		map[int32]int32 	// 已经创建好的可使用的缓存 id 列表
	c 			chan int32
}

var shortIdCreator = userShortId{make(map[int32]int32), make(map[int32]int32), make(chan int32)}

// 初始化用户短 id 生成器 usedIds: 已经被使用的 keeps: 要保留的
func InitShortUserId(usedIds []int32, keeps []int32) {
	shortIdCreator.usedIds = make(map[int32]int32)
	shortIdCreator.liveIds = make(map[int32]int32)
	for _, v := range usedIds {
		shortIdCreator.usedIds[v] = v
	}
	for _, v := range keeps {
		shortIdCreator.usedIds[v] = v
	}

	go func() {
		defer func() {
			if err := recover(); err != nil {
				fmt.Println(err)
			}
		} ()
		var startIndex int32 = 100000
		for {
			if len(shortIdCreator.liveIds) < int(startIndex) / 10 {
				endIndex := startIndex * 10 -1
				for i := startIndex; i < endIndex; i ++ {
					if _, ok := shortIdCreator.usedIds[i]; !ok {
						shortIdCreator.liveIds[i] = i
					}
				}
				startIndex *= 10
			}
			for k, v := range shortIdCreator.liveIds {
				shortIdCreator.c <- v
				delete(shortIdCreator.liveIds, k)
				shortIdCreator.usedIds[k] = v
				break
			}
		}
	} ()
}

// 生成用户短 id
func GetShortUserId() int32 {
	return <- shortIdCreator.c
}

// 生成 token
func GetToken() string {
	return fmt.Sprintf("%x", md5.Sum([]byte(strconv.FormatInt(time.Now().Unix(), 10))))
}

// 加密密码，md5(md5(password + salt) + public_salt) 密码 私钥 公钥
func EncryptPassword(password, salt, publicSalt string) string {
	saltedPassword := fmt.Sprintf("%x", md5.Sum([]byte(password))) + salt
	md5SaltedPassword := fmt.Sprintf("%x", md5.Sum([]byte(saltedPassword)))
	return fmt.Sprintf("%x", md5.Sum([]byte(md5SaltedPassword + publicSalt)))
}